
local itercache = require 'dclm.cache.iterator'

-- our custom iterator function
local function f(n, m)
  coroutine.yield(n + m)
  coroutine.yield(10*n + m)
  coroutine.yield(100*n + m)
end

-- usual way of doing it
local function f_iter_standard(n, m)
  return coroutine.wrap(function()  f(n, m);  end)
end

-- cached 
local function f_iter_cached(n, m)
  return itercache.get(f, n, m)
end

local function sweepgarbage()
  local count = collectgarbage('count')
  while true do
    collectgarbage()
	local new_count = collectgarbage('count')
	if new_count == count then
	  break
	end
	count = new_count
  end
end

sweepgarbage()
local before = collectgarbage('count')

local x = 0

-- turn off the garbage collector to illustrate how much it needs to deal with
collectgarbage('stop')

for i = 1,1000 do
  for i in f_iter_standard(5, 1) do
    for j in f_iter_standard(5, 1) do
      x = (x + i) % j
	end
  end
end
print('bytes allocated over 1000 x standard:', collectgarbage('count') - before)

sweepgarbage()

collectgarbage('stop')

before = collectgarbage('count')
for i = 1,1000 do
  for i in f_iter_cached(5, 1) do
    for j in f_iter_cached(5, 1) do
      x = (x + i) % j
	end
  end
end
print('bytes allocated over 1000 x cached:', collectgarbage('count') - before)
